package QRCG;

import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class PlayGameServe
 */
@WebServlet("/PlayGameServe")
public class PlayGameServe extends HttpServlet {
	private static final long serialVersionUID = 2453785400917898551L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public PlayGameServe() {
		super();
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// {@code response.sendRedirect} loses request attributes, so {@code
		// RequestDispatcher.forward is used}.
		RequestDispatcher rd = request.getRequestDispatcher("PlayGame.jsp");
		HttpSession session = request.getSession();

		String nickname = (String) session.getAttribute("nickname");

		String gameId = (String) session.getAttribute("game_id");
		// gameId = (String) request.getAttribute("game_id");
		// gameId = (String) request.getParameter("game_id");
		String message = "";
		
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String user_ends = df.format(new Date());

		DatabaseManager dm = new DatabaseManager();
		try {
			dm.connect();
		} catch (SQLException e) {
			e.printStackTrace();

			message = "Something went wrong, please try again.";
			request.setAttribute("game_id", gameId);
			request.setAttribute("message", message);
			rd.forward(request, response);
		}

		if (!Util.hasTextContent(gameId)) {
			message = "There is no such game.";
		} else {
			message = "The keyword is not correct, try again.";

			String keyword = request.getParameter("keyword_all_at_once");
						
			if (Util.hasTextContent(keyword)) {
				//
				// game type is "all hints at once"
				message = "";

				String levelId = dm.checkAllLevelKeywords(gameId, keyword.toLowerCase());

				if (Util.hasTextContent(levelId)) {

					String userId = dm.getUserInformation(DatabaseManager.UserInformation.ID,
							nickname);
					String query = "INSERT INTO PlayerHistory (game_id, user_id, level_id) VALUES("
							+ gameId + "," + userId + "," + levelId + ")";
					boolean success = true;
					try {
						success = dm.execute(query);
					} catch (SQLException e) {
						e.printStackTrace();

						message = "Something went wrong, please try again.";
						request.setAttribute("game_id", gameId);
						request.setAttribute("message", message);
						rd.forward(request, response);
					}
					if (success) {
						if (dm.isGameFinished(gameId, nickname)) {
							//update the finish time of the user
							query = "UPDATE GamePlayers SET user_ends ='" + user_ends + "' WHERE game_id=" + gameId
									+ " AND user_id=" + userId;
							try {
								dm.execute(query);
							} catch (SQLException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							message = "Congratulations! You just finished the game!";
						} else {
							message = "Well done! You have completed level " + levelId;
						}
					} else {
						message = "Something went wrong, please try again.";
					}
				} else {
					message = "The keyword did not match any of the levels, try again.";
				}

			} else {
				keyword = request.getParameter("keyword_step_by_step");
				
				if (Util.hasTextContent(keyword)) {
					//
					// game type is "step by step"
					message = "";

					String userId = dm.getUserInformation(DatabaseManager.UserInformation.ID,
							nickname);

					String codeQuery = "SELECT gl.level_id, gl.level_code FROM GameLevels gl WHERE gl.game_id = "
							+ gameId + "";
					ArrayList<HashMap<String, Object>> resultSet = dm.executeSelectQuery(codeQuery);

					String levelId = null;
					boolean continueLoop = true;
					boolean isCodeMatched = false;
					int i = 0;
					while (continueLoop) {
						String correctKeyword = (String) resultSet.get(i).get("level_code");
						correctKeyword = correctKeyword.toLowerCase();
						
						levelId = Integer.toString((Integer) resultSet.get(i).get("level_id"));

						isCodeMatched = ((keyword.toLowerCase()).equals(correctKeyword));

						i++;
						continueLoop = (i < resultSet.size());
						if (continueLoop) {
							continueLoop = !isCodeMatched;
						}
					}

					if (isCodeMatched) {

						String query = "INSERT INTO PlayerHistory (game_id, user_id, level_id) VALUES("
								+ gameId + "," + userId + "," + levelId + ")";
						boolean success = true;
						try {
							success = dm.execute(query);
						} catch (SQLException e) {
							e.printStackTrace();

							message = "Something went wrong, please try again.";
							request.setAttribute("game_id", gameId);
							request.setAttribute("message", message);
							rd.forward(request, response);
						}
						if (success) {

							String currentLevelId = request.getParameter("current_level_id");

							if (levelId.equalsIgnoreCase(currentLevelId)) {
								if (dm.isGameFinished(gameId, nickname)) {
									query = "UPDATE GamePlayers SET user_ends ='" + user_ends + "' WHERE game_id=" + gameId
											+ " AND user_id=" + userId;
									try {
										dm.execute(query);
									} catch (SQLException e) {
										// TODO Auto-generated catch block
										e.printStackTrace();
									}
									message = "Congratulations! You just finished the game!";
								} else {
									message = "Well done! You have reached the next level.";
								}
							} else {
								message = "Well done! You have reached the next level.<br>However you have found the keyword for the level "
										+ levelId
										+ ".<br>You still need to find the one for level "
										+ currentLevelId + ".";
							}
						} else {
							message = "Something went wrong, please try again.";
						}
					} else {
						message = "The keyword is not correct, try again.";
					}
				}
			}
		}

		System.out.println(message);
		request.setAttribute("game_id", gameId);
		request.setAttribute("message", message);
		rd.forward(request, response);
	}

	public static boolean isInputEnabled(HttpServletRequest request, DatabaseManager dbManager,
			String nickname, String gameId) {

		boolean inputEnabled = true;
		String levelMessage = "";
		String currentLevelId = "";
		String currentLevelHint = "";

		if (dbManager.isUserRegisteredToGame(nickname, gameId)) {
			
			dbManager.startUserGameTimer(nickname, gameId);

			if (dbManager.isGameFinished(gameId, nickname)) {
				inputEnabled = false;
				levelMessage = "Congratulations! You already finished this game.";
			} else {
				currentLevelId = dbManager.getUserCurrentLevel(nickname, gameId);

				if (Util.hasTextContent(currentLevelId)) {

					currentLevelHint = dbManager.getLevelInformation(
							DatabaseManager.LevelInformation.HINT, gameId, currentLevelId);

				} else {
					inputEnabled = false;
					levelMessage = "Error: This game has some missing level information.";
				}
			}
		} else {
			inputEnabled = false;
			levelMessage = "You are not registered to this game.";
		}
		if (!Util.hasTextContent((String) request.getAttribute("message"))) {
			request.setAttribute("level_message", levelMessage);
		}
		request.setAttribute("current_level_hint", currentLevelHint);
		request.setAttribute("current_level_id", currentLevelId);
		return inputEnabled;
	}

}
